/*************************************************************************
    Projet  -  Sport Collectif pour Robots
                             -------------------
    Auteur  -  Maxime Swinnen
*************************************************************************/

//---------- Interface de la classe <strategie> (fichier strategie.h) -------
#ifndef STRATEGIE_H_
#define STRATEGIE_H_


//------------------------------------------------------------------------ 
// Role de la classe <strategie>
// Ce module a pour role d'etudier les conditions de jeu de la partie
// en cours afin de choisir la strategie adaptee a appliquer
//------------------------------------------------------------------------ 


//--------------------------------------------------- Interfaces utilisees
#ifdef __APPLE__	// mac
#include <opencv/openCV.h>
#endif

#ifdef __linux__	// gcc (egcs) on linux
#include <opencv.hpp>
#endif

#include "../util.h"
#include "../MsgQueue.h"
#include "../Vision/VideoSource.h"

//-------------------------------------------------------------- Variables
extern Vec2d afficheObjectifRobotG;
extern Vec2d afficheObjectifRobotD;

//------------------------------------------------------------- Constantes
#define POSITION_CORRECTE 1
#define POSITION_HORS_LIMITES -1
#define POSITION_HORS_COULOIR -2
#define POSITION_HORS_MOITIE -3
//------------------------------------------------------------------ Types 

struct DataIA
{
	char typeStrategie;
	Vec2d posObjectif;
	Vec2d dirObjectif;
};

// Added by MATUchifra :
enum Tir_Type
{
	Long,
	Defaut,
	Court
};

using namespace cv;

//------------------------------------------------------------------------
// Rôle de la classe <Strategie>
//
//
//------------------------------------------------------------------------
class Strategie
{
	public:

		Strategie(MsgQueue<DataIA>* msgQRG, MsgQueue<DataIA>* msgQRD, MsgQueue<DataVision>* msgQVis);
		// Mode d'emploi :
		//	Constructeur
		//	Executee a la creation du Thread de gestion de l'IA

		bool LancerStrategie();
		// Mode d'emploi :

		int ArreterStrategie();
		// Mode d'emploi :

		~Strategie();
		// Destructeur de la classe

	protected:

		Vec2d positionAvRobotGauche;
		Vec2d positionAvRobotDroite;
		Vec2d positionArRobotGauche;
		Vec2d positionArRobotDroite;

		// Add by matuchiFRA
		Vec2d positionDefRobotGauche;
		Vec2d dirDefRobotGauche;
		Vec2d positionDefRobotDroite;
		Vec2d dirDefRobotDroite;
		Vec2d positionSoutienRobotGauche;
		Vec2d positionSoutienRobotDroite;
		// end add
		
		// Added by MAtuchifra
		Vec2d positionRobotAdvGauche;
		Vec2d positionRobotAdvDroite;
		// end add

		// Pour la balle
		Vec2d vitesseBalle;
		Position positionBalle;
		Position positionPrecedenteBalle;
		double valeurVitesseBalle;

		Vec2d directionBut;
		Position positionRobotGauche;
		Position positionRobotDroite;
		DataIA ancienMsgObjRG;
		DataIA ancienMsgObjRD;
		DataIA msgObjectifRG;
		DataIA msgObjectifRD;
		MsgQueue<DataVision>* msgQueueVision;
		MsgQueue<DataIA>* msgQueueControleRG;
		MsgQueue<DataIA>* msgQueueControleRD;
		bool strategieThreadLoop;
		pthread_t strategieThreadId;
		pthread_t stopStrategieThreadId;
		pthread_mutex_t lockStrategieThreadLoop;
		pthread_mutex_t lockStopStrategieThread;
		double distanceAncienObj;
		long dateDernierEnvoiG;
		long dateDernierEnvoiD;
		// Detection aberrations vecteur vitesse balle
		Vec2d vecteurBalleRef;
		Vec2d vecteurBallePrec;
		unsigned int compteurAberrations;

		bool defenseEnCours;

		struct val_st<Strategie>* stopStrategieParams;
		struct val_st<Strategie>* strategieParams;

		void evaluer();
		void attaquer();
		void defendre();
		void replacer();
		bool envoyerMessageRobotGauche(DataIA messageAenvoyer);
		bool envoyerMessageRobotDroite(DataIA messageAenvoyer);
		int validerObjectif(int idRobot);

		bool detecterAberrations(const Vec2d nouveauVecteurVitesse);

		void strategieThread();
		void stopStrategieThread();
		void (Strategie::*strategieThreadWrapper())() {
			return &Strategie::strategieThread;
		}
		void (Strategie::*stopStrategieThreadWrapper())() {
			return &Strategie::stopStrategieThread;
		}

		// Add by Matuchifra team
		double distancePosObjectif(DataIA d1, DataIA d2);
		bool balleDansNotreCamp();
		bool balleVaVersNotreBut();
		bool balleAGauche();
		bool balleADroite();
		Vec2d & pointIntersectionLigneDeBut(const Vec2d & prevPosBall, const Vec2d & nextPosBalle);

		// Added by MAtuchifra
		Tir_Type ChoisirTirType();
		double ChoisirVerticalDistanceTir();
		// add end

	private:

		Strategie();
};

//----------------------------------------- Types dépendants de <Strategie>

#endif // STRATEGIE_H_
